package com.opages.mvc.adapter.common.condition;

import java.util.*;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;

import com.opages.mvc.adapter.common.condition.annotation.ConditionalOnMissingBean;
import com.opages.mvc.adapter.common.condition.core.ConditionOutcome;
import org.springframework.core.type.MethodMetadata;

/**
 * srping容器中bean不存在则返回真,表示可以注入
 * @author daizhong.liu
 * @create 2020-07-02 14:06
 **/
public class OnMissingBeanCondition extends AnnotationCondition implements ConfigurationCondition {
    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(ConditionalOnMissingBean.class.getName());
        Object annotationVal = annotationAttributes.get("value");
        List<Object> clazzs = new ArrayList<>();
        if(annotationVal == null || ((Class[]) annotationVal).length <= 0) {
            if(metadata instanceof MethodMetadata) {
                MethodMetadata methodMetadata = (MethodMetadata) metadata;
                String returnTypeName = methodMetadata.getReturnTypeName();
                try {
                    clazzs.add(Class.forName(returnTypeName));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }else {
            Class[] classes = (Class[]) annotationVal;
            if(classes.length > 1) {
                clazzs.addAll(Arrays.asList(classes));
            }else {
                clazzs.add(annotationVal);
            }
        }
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        try {
            if (beanFactory != null) {
                for(Object clazz : clazzs) {
                    context.getBeanFactory().getBean(clazz.getClass());
                }
                //获取不到对象会抛出异常就不会经过noMatch
                return ConditionOutcome.noMatch();
            }
        }catch (NoSuchBeanDefinitionException e){}
        return ConditionOutcome.match();
    }

    @Override
    public ConfigurationPhase getConfigurationPhase() {
        return ConfigurationPhase.REGISTER_BEAN;
    }
}
